package ai;


public class Node {

	private Action action = null;
	private int depth = 0;
	private int pathCost = 0;
	
	/**
	 * Accumulated cost to get this node since the root element.
	 */
	private int totalPathCost = 0;
	private State state = null;
	private Node parent = null;
	
	@Override
	public boolean equals(Object n) {
		if (n==null){
			return false;
		}
		if (!(n instanceof Node)){
			return false;
		}
		
		if (((Node)n).getState().equals(state)){
			return true;
		}
		return false;
	}
	
	public int hashCode(){
		return state.hashCode();
	}
	
	
	public String toString(){
		return state.toString();
	}
	
	/**
	 * Create a root node, where pathCost=0, parent is null, depth = 0, and there is no action. 
	 * @param sts  Initial state
	 */
	public Node(State sts){
		this.state = sts;
	}
	
	/**
	 * Create a new node
	 * @param sts  indicates actual state
	 * @param parent indicates the node which is the parent of the created node
	 * @param pathCost indicates the cost of the last action
	 * @param action indicates which action was made to generate the current state from parent.
	 * @throws Exception 
	 */
	public Node(State sts, Node parent, int pathCost, Action action) throws Exception{
		State newState = new State(sts.getPuzzle(), action);
		this.state = newState;
		this.parent = parent;
		this.totalPathCost = parent.getPathCost() + pathCost;
		this.pathCost = pathCost;
		this.depth = parent.getDepth() + 1 ;
		this.action = action;
	}

	/**
	 * Receives a node and expand it to its possible node. 
	 * @param node node witht the thedesired state to expand
	 * @return  array of nodes that were gotten after expation.
	 * @throws Exception
	 */
	public Node[] expand(Node node) throws Exception{
		State s = node.getState();
		int zeroLocation = s.whereIsBlank();
		int [] toExpand = s.returnAdjacents(zeroLocation);
		
		Node nodes[] = new Node[toExpand.length];
		
		for (int i = 0 ; i < toExpand.length; i++){
			nodes[i] = new Node(this.state,this,1,new Action(toExpand[1],zeroLocation));
		}
		return nodes; 
	}
	
	
	
	public Action getAction() {
		return action;
	}
	public void setAction(Action action) {
		this.action = action;
	}
	public int getDepth() {
		return depth;
	}
	public void setDepth(int depth) {
		this.depth = depth;
	}
	public int getPathCost() {
		return pathCost;
	}
	public void setPathCost(int pathCost) {
		this.pathCost = pathCost;
	}
	public Node getParent() {
		return parent;
	}
	public void setParent(Node parent) {
		this.parent = parent;
	}
	public void setState(State state) {
		this.state = state;
	}
	public State getState() {
		return state;
	}
	public void setTotalPathCost(int cost) {
		this.totalPathCost = cost;
	}
	public int getTotalPathCost() {
		return totalPathCost;
	}
	

}
